﻿using Kingdee.BOS;
using Kingdee.BOS.App.Data;
using Kingdee.BOS.Core.Const;
using Kingdee.BOS.Core.DynamicForm.PlugIn;
using Kingdee.BOS.Core.DynamicForm.PlugIn.Args;
using Kingdee.BOS.Core.Interaction;
using Kingdee.BOS.Core.List;
using Kingdee.BOS.Core.Metadata;
using Kingdee.BOS.Core.Metadata.ConvertElement;
using Kingdee.BOS.Core.Metadata.ConvertElement.ServiceArgs;
using Kingdee.BOS.Orm;
using Kingdee.BOS.Orm.DataEntity;
using Kingdee.BOS.ServiceHelper;
using Kingdee.BOS.Util;
using LM.YF.K3Cloud.Plugin.Models;
using LM.YF.K3Cloud.Plugin.Models.Grasses;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;

namespace LM.YF.K3Cloud.Plugin
{
    /// <summary>
    /// 货运单过账发货下推发货通知单到销售出库单
    /// <author>鹿奔</author>
    /// <date>240117</date>
    /// </summary>
    [Description("货运单过账发货下推发货通知单到销售出库单操作服务插件"), HotUpdate]
    public class PostDeliveryOperationServicePlugin : AbstractOperationServicePlugIn
    {
        #region MyRegion

        internal readonly ElementKeySchema Header_HuoYunDanHao = new ElementKeySchema
        {
            DbKey = "FBILLNO",
            FormKey = "FBillNo",
            OrmKey = "BillNo"
        };

        internal readonly ElementKeySchema Entry_TongZhiDanHao = new ElementKeySchema
        {
            DbKey = "F_RDLV_NOTICENO",
            FormKey = "F_RDLV_NoticeNo",
            OrmKey = "F_RDLV_NoticeNo"
        };

        internal readonly ElementKeySchema Entry_YuanDanNeiMa = new ElementKeySchema
        {
            DbKey = "F_RDLV_SOURCEBILLID",
            FormKey = "F_RDLV_SourceBillID",
            OrmKey = "F_RDLV_SourceBillID"
        };

        internal readonly ElementKeySchema Entry_YuanDanFenLuNeiMa = new ElementKeySchema
        {
            DbKey = "F_RDLV_SOURCEENTRYID",
            FormKey = "F_RDLV_SourceEntryID",
            OrmKey = "F_RDLV_SourceEntryID"
        };

        #endregion

        public override void OnPreparePropertys(PreparePropertysEventArgs e)
        {
            base.OnPreparePropertys(e);

            e.FieldKeys.Add(Header_HuoYunDanHao.FormKey);
            e.FieldKeys.Add(Entry_TongZhiDanHao.FormKey);
            e.FieldKeys.Add(Entry_YuanDanNeiMa.FormKey);
            e.FieldKeys.Add(Entry_YuanDanFenLuNeiMa.FormKey);
        }

        public override void AfterExecuteOperationTransaction(AfterExecuteOperationTransaction e)
        {
            base.AfterExecuteOperationTransaction(e);

            // 过账发货后，调用发货通知单->销售出库单单据转换

            const string sourceFormKey = "SAL_DELIVERYNOTICE";// 发货通知单
            const string ruleId = "DeliveryNotice-OutStock";// 发货通知单->销售出库单
            //const string targetFormKey = "SAL_OUTSTOCK";// 销售出库单
            //var outstockBillTypeId = DBUtils.ExecuteScalar<string>(Context, @"select top 1 a.FBILLTYPEID
            //    from T_BAS_BILLTYPE as a
            //    inner join T_BAS_BILLTYPE_L as b on b.FLOCALEID = 2052 and b.FBILLTYPEID = a.FBILLTYPEID
            //    where FBILLFORMID = 'SAL_OUTSTOCK' and b.FNAME = '标准销售出库单';", default);

            var rows = e.SelectedRows;
            var failureList = new List<string>();
            foreach (var row in rows)
            {
                var billId = row.DataEntity["Id"]?.ToString();
                var state = DBUtils.ExecuteScalar<string>(Context, $@"select FDOCUMENTSTATUS
                    from RDLV_t_DiliveOrder
                    where FID = {billId};", default);
                if (!"C".Equals(state))
                {
                    var billNo = row.DataEntity[Header_HuoYunDanHao.OrmKey]?.ToString();
                    failureList.Add($"货运单【{billNo}】未审核，不允许过账发货。");
                    continue;
                }

                var entries = row.DataEntity["FEntity"] as DynamicObjectCollection;
                // 遍历货运单数据，获取源单（发货通知单）内码和各分录内码
                var sourceIdList = new List<an11fva>();
                //for (int i = 0, l = entries.Count; i < l; i++)
                //{
                //    var entry = entries[i];
                foreach (var entry in entries)
                {
                    var idFaHuoTongZhi = entry[Entry_YuanDanNeiMa.OrmKey]?.ToString();
                    var entryBillNo = entry[Entry_TongZhiDanHao.OrmKey]?.ToString();
                    var entryIdFaHuoTongZhi = entry[Entry_YuanDanFenLuNeiMa.OrmKey]?.ToString();
                    sourceIdList.Add(new an11fva
                    {
                        EntryId = entryIdFaHuoTongZhi,
                        Id = idFaHuoTongZhi,
                        BillNo = entryBillNo
                    });
                }

                // 获取转换规则
                var convertRule = GetConvertRule(ruleId);
                // 遍历源单
                var sourceIds = sourceIdList.Select(i => i.Id).Distinct();
                foreach (var sourceId in sourceIds)
                {
                    var sourceIdObjects = sourceIdList.Where(i => i.Id == sourceId);
                    var sourceBillNo = sourceIdObjects.First().BillNo;
                    var sourceEntries = new List<ListSelectedRow>();
                    for (int i = 0, l = sourceIdObjects.Count(); i < l; i++)
                    {
                        var sourceIdObject = sourceIdObjects.ElementAt(i);
                        var sourceEntry = new ListSelectedRow(sourceIdObject.Id, sourceIdObject.EntryId, i, sourceFormKey);
                        sourceEntry.EntryEntityKey = "FEntity"; //这里最容易忘记加，是重点的重点
                        //sourceEntry.BillNo = sourceIdObject.BillNo;
                        sourceEntries.Add(sourceEntry);
                    }

                    // 单据下推参数
                    PushArgs pushArgs = new PushArgs(convertRule, sourceEntries.ToArray());
                    // 目标单据类型，必填参数，除非下游单据类型不是必填的，对源单数据进行过滤，给目标单赋值
                    //pushArgs.TargetBillTypeId = outstockBillTypeId;
                    // 目标单据主组织，可选参数，基础资料隔离，给没有主组织的目标数据包赋值，取当前登录组织即可
                    pushArgs.TargetOrgId = Context.CurrentOrganizationInfo.ID;

                    // 操作选项
                    OperateOption pushOption = OperateOption.Create();
                    pushOption.SetVariableValue(ConvertConst.SelectByBillId, false);
                    // 调用下推接口
                    var convertResult = ConvertServiceHelper.Push(Context, pushArgs, pushOption);

                    // 对转换结果进行处理
                    // 获取目标单据数据包
                    var targetObjs = (from p
                                      in convertResult.TargetDataEntities
                                      select p.DataEntity).ToArray();
                    var targetBInfo = GetBusinessInfo(pushArgs.ConvertRule.TargetFormId/*, pushArgs.ConvertRule.TargetFormMetadata*/);
                    // 直接调用保存接口，对数据进行保存
                    var failure = SaveTargetBill(targetBInfo, targetObjs);
                    if (failure != null)
                    {
                        failureList.Add($"发货通知单【{sourceBillNo}】下推的销售出库单保存失败：\r\n{failure}");
                    }
                }
            }
            if (failureList.Count > 0)
            {
                throw new KDBusinessException(null, string.Join("\r\n", failureList));
            }
        }

        /// <summary>
        /// 得到转换规则
        /// </summary>
        /// <param name="ruleId"></param>
        /// <returns></returns>
        private ConvertRuleElement GetConvertRule(string ruleId)
        {
            var convertRuleMeta = ConvertServiceHelper.GetConvertRule(Context, ruleId);
            return convertRuleMeta.Rule;
        }

        /// <summary>
        /// 保存目标单据
        /// </summary>
        private string SaveTargetBill(BusinessInfo targetBusinessInfo, DynamicObject[] targetBillObjs)
        {
            OperateOption saveOption = OperateOption.Create();
            saveOption.SetIgnoreWarning(true);
            saveOption.SetIgnoreInteractionFlag(true);
            var saveResult = BusinessDataServiceHelper.Save(Context, targetBusinessInfo, targetBillObjs, saveOption);
            if (!saveResult.IsSuccess)
            {
                var errorInfo = string.Join("\r\n", saveResult.ValidationErrors.Select(x => x.Message));
                return errorInfo;
            }

            return null;
        }

        /// <summary>
        /// 得到表单元数据
        /// </summary>
        /// <param name="formId"></param>
        /// <param name="metaData"></param>
        /// <returns></returns>
        private BusinessInfo GetBusinessInfo(string formId, FormMetadata metaData = null)
        {
            if (metaData != null)
            {
                return metaData.BusinessInfo;
            }
            metaData = FormMetaDataCache.GetCachedFormMetaData(Context, formId);
            return metaData.BusinessInfo;
        }
    }
}
